import 'package:dio/dio.dart';
import 'package:flutter_axios/flutter_axios.dart' hide Interceptor, ProgressCallback;
import 'base_http_client.dart';
import 'config/api_config.dart';
import 'exceptions/app_exceptions.dart';
import 'models/api_response.dart';

class AxiosHttpClient extends BaseHttpClient {
  late AxiosInstance _api;
  String _baseUrl = ApiConfig.baseUrl;
  Map<String, String> _headers = ApiConfig.defaultHeaders;
  Duration _connectTimeout = ApiConfig.connectTimeout;
  Duration _receiveTimeout = ApiConfig.receiveTimeout;
  Duration _sendTimeout = ApiConfig.sendTimeout;

  AxiosHttpClient() {
    _initAxios();
  }

  void _initAxios() {
    _api = Axios.create(
      AxiosConfig(
        baseURL: _baseUrl,
        timeout: _connectTimeout,
        headers: _headers,
      ),
    );
  }

  @override
  void setBaseUrl(String baseUrl) {
    _baseUrl = baseUrl;
    _initAxios();
  }

  @override
  void setHeaders(Map<String, String> headers) {
    _headers = {..._headers, ...headers};
    _initAxios();
  }

  @override
  void setTimeout(Duration connectTimeout, Duration receiveTimeout, Duration sendTimeout) {
    _connectTimeout = connectTimeout;
    _receiveTimeout = receiveTimeout;
    _sendTimeout = sendTimeout;
    _initAxios();
  }

  @override
  void addInterceptor(Interceptor interceptor) {}

  @override
  void removeInterceptor(Interceptor interceptor) {}

  @override
  void clearInterceptors() {}

  @override
  Future<ApiResponse<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.get(_buildUrl(path, queryParameters)),
    );
  }

  @override
  Future<ApiResponse<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.post(_buildUrl(path, queryParameters), data: data),
    );
  }

  @override
  Future<ApiResponse<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.put(_buildUrl(path, queryParameters), data: data),
    );
  }

  @override
  Future<ApiResponse<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.delete(_buildUrl(path, queryParameters)),
    );
  }

  @override
  Future<ApiResponse<T>> patch<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.patch(_buildUrl(path, queryParameters), data: data),
    );
  }

  @override
  void cancelRequest(String requestId) {}

  @override
  void cancelAllRequests() {}

  @override
  Future<ApiResponse<T>> upload<T>(
    String path, {
    required String filePath,
    required String fileKey,
    Map<String, dynamic>? data,
    ProgressCallback? onSendProgress,
    Options? options,
    String? requestId,
  }) async {
    throw UnimplementedError();
  }

  @override
  Future<ApiResponse<T>> download<T>(
    String path, {
    required String savePath,
    ProgressCallback? onReceiveProgress,
    Map<String, dynamic>? queryParameters,
    Options? options,
    String? requestId,
  }) async {
    return _executeRequest<T>(
      () async => await _api.get(_buildUrl(path, queryParameters)),
    );
  }

  @override
  void setAuthToken(String token) {
    _headers = {..._headers, 'Authorization': 'Bearer $token'};
    _initAxios();
  }

  @override
  void clearAuthToken() {
    _headers = Map.from(_headers)..remove('Authorization');
    _initAxios();
  }

  @override
  bool isNetworkError(DioException error) {
    return error.type == DioExceptionType.connectionTimeout ||
        error.type == DioExceptionType.sendTimeout ||
        error.type == DioExceptionType.receiveTimeout ||
        error.type == DioExceptionType.connectionError ||
        error.type == DioExceptionType.unknown;
  }

  @override
  bool isServerError(int statusCode) {
    return statusCode >= 500 && statusCode < 600;
  }

  @override
  void dispose() {}

  String _buildUrl(String path, Map<String, dynamic>? query) {
    if (query == null || query.isEmpty) return path;
    final uri = Uri(path: path, queryParameters: query.map((k, v) => MapEntry(k, v?.toString())));
    return uri.toString();
  }

  Future<ApiResponse<T>> _executeRequest<T>(
    Future<AxiosResponse> Function() request,
  ) async {
    try {
      final response = await request();
      final data = response.data as T;
      final headers = response.headers;
      final status = response.status;
      return ApiResponse.success(
        data,
        statusCode: status ?? 200,
        headers: headers,
      );
    } catch (e) {
      throw _handleAxiosError(e);
    }
  }

  AppException _handleAxiosError(Object error) {
    final msg = error.toString();
    if (msg.contains('Timeout')) {
      return TimeoutException('请求超时，请检查网络连接');
    }
    if (msg.contains('Network') || msg.contains('Socket')) {
      return NetworkException('网络连接失败，请检查网络设置');
    }
    if (msg.contains('401')) {
      return AuthenticationException('身份验证失败');
    }
    if (msg.contains('404')) {
      return ServerException('资源未找到', 404);
    }
    return UnknownException('未知错误: $msg');
  }
}